/*
 * @Author: wuzhouhai wzh200x@126.com
 * @Date: 2024-03-20 14:01:01
 * @LastEditors: wzh200x@126.com
 * @LastEditTime: 2025-08-21 13:37:48
 * @FilePath: \dwys_web\extensions\phoenix-plugin-client\assets\core\Phoenix.ts
 * @Description:
 */
import { LoginAccountInput } from './dto/login-account.input';
import { Account } from './entities/Account';
import { Avatar } from './entities/Avatar';
import { PhoenixHttpClient } from './http/PhoenixHttpClient';
import { Utils } from './utils/Utils';
import { AccountResponse } from './response/account.response';
import { ErrorLocalCode } from './defines/error.local.define';
import { CreateAvatarInput } from './dto/create-avatar.input';
import { AvatarResponse } from './response/avatar.response';
import { GetAvatarInput } from './dto/get-avatar.input';
import { UtilsString } from './utils/Utils.String';
import { UpdateAvatarInput } from './dto/update-avatar.input';
import { AvatarUpdateResponse } from './response/avatar.update.response';
import { UpdateTokenInput } from './dto/update-token.input';
import { UpdateTokenResponse } from './response/update.token.response';
import { UpdateAccountInput } from './dto/update-account.input';
import { UpdateServerTimeInput } from './dto/get-serverTime.input';
import { PlatformDefine } from './defines/platform.define';
import { IPlatform } from './interface/platform.interface';
import { PlatformManager } from './platform/platformManager';
import {PhoenixRoot} from './PhoenixRoot';
import { AlipayReportInput } from './dto/alipay.report.input';
import { ServerInfoResponse } from './response/server.response';
import { InputBase } from './dto/input-base';
import { QueryAccountInput } from './dto/query-account.input';
import { CenterUpdateInput } from './dto/center-update.input';
import { CallThirdInput } from './dto/call-third.input';
import { LoginPlatformInput } from './dto/platform-login.input';
import { PlatformResponse } from './response/platform.response';
import { WebSocketClient } from "./net/webSocketClient/webSocketClient";
import messageManager from './managers/message.manager';
import { Opcode } from './defines/opcode.define';
import { C2S_MessageLogin } from './net/message/gameMessage/c2s/c2sMessage_login';
import { S2C_MessageLogin } from './net/message/gameMessage/s2c/s2cMessage_login';
import { Packet } from './net/packet/packet';
import { IModelData } from './interface/iModelData';
import { S2C_MessageKick } from './net/message/gameMessage/s2c/s2cMessage_kick';
import { UseCdkeyInput } from './dto/use.cdkey.input';
import { BytejumpReportInput } from './dto/bytejump.report.input';
import { BytejumpGetEcpmInput } from './dto/bytejump.getEcpm.input';
import { KuaiShouReportInput } from './dto/kuaishou.report.input';
import { UpdateAvatarModuleInput } from './dto/update-module.input';
import { GetAvatarModuleInput } from './dto/get-module.input';
import { AvatarModuleResponse } from './response/avatar.module.reponse';
import { SubscribeInput } from './dto/subscribe.input';
import { OrderCreateInput } from './dto/order.create.input.';
import { OrderQueryInput } from './dto/order.query.input';
import { OrderPayedInput } from './dto/order.payed.input';
import { OrderSendInput } from './dto/order.sendGoods.input';
import { StoreDelInput, StoreGetInput, StoreSetInput } from './dto/storeSet.input';
import { ShortLinkInput, WxQRCodeInput } from './dto/wxScheme.input';
import { CardChooseInput } from './dto/card-choose.input';
const Phoenix_Version = '1.0.2.8_1.0.4.12_1.0.1.4';   // 客户端版本,与服务器版本[最低_最高]对应,不能高于服务器版本
export class Phoenix {
    private platform: number = PlatformDefine.PhoenixGame;
    private platformHelp: IPlatform|null = null;
    private httpClient: PhoenixHttpClient| null = null;
    private gameServerHttpClient: PhoenixHttpClient | null = null;
    private gameWebsocket:WebSocketClient | null = null;
    private account: Account | null = null;
    private avatar: Avatar | null = null;
    private serverTimer: number = 0;
    private phoenixRoot: PhoenixRoot|null = null;
    private serverInfo: ServerInfoResponse | null = null;
    private selectServerZone: number = 0;
    private thirdCallBackData: any;
    private port: string = '';
    private isSSL: boolean = false;
    private avatarModel: IModelData | null = null;
    private centerIndex: number = 0;
    private allCenterServerHosts: string[] = [];     // 所有中心服地址,会轮询进行尝试
    private centerSecretKey: string = '';
    private isInit = false;
    
    constructor() {}

    public init(platform: number, hosts: string[], port: string, isSSL: boolean, secretKey?: string) {
        this.selectServerZone = -1;
        this.platform = platform;
        this.platformHelp = PlatformManager.GeneratePlatform(platform)!;
        this.port = port;
        this.isSSL = isSSL;
        this.allCenterServerHosts = hosts;
        this.centerSecretKey = secretKey ?? '';
        this.httpClient = new PhoenixHttpClient(this.platformHelp!, hosts[0], this.port, this.isSSL, this.centerSecretKey);
    }

    initMessage(){
        messageManager.registerMessage(Opcode.Opcode_CS_LOGIN, ()=>{
            return new C2S_MessageLogin();
        });

        messageManager.registerMessage(Opcode.Opcode_SC_LOGIN, ()=>{
            return new S2C_MessageLogin();
        });
        messageManager.registerMessage(Opcode.Opcode_SC_KICK, ()=>{
            return new S2C_MessageKick();
        });
    }
    
    public setAppId(appId: string) {
        this.platformHelp?.setAppId(appId);
    }

    public InitPhoenix() {
        if (this.isInit) {
            return;
        }
        this.isInit = true;
    }

    public CheckIsInit():boolean{
        return this.isInit;
    }

    public PhoenixVersion(): string {
        return Phoenix_Version;
    }

    public switchCenterServer():boolean{
        if (this.centerIndex >= this.allCenterServerHosts.length - 1) {
            this.httpClient = null;
            return false;
        }
        this.centerIndex++;
        let host = this.allCenterServerHosts[this.centerIndex];
        this.httpClient?.setBaseUrl(host, this.port, this.isSSL);
        return true;
    }

    public bindAvatarModel(avatarModel: IModelData){
        this.avatarModel = avatarModel;
        if(this.avatar){
            this.avatar.setAvatarDataModel(avatarModel);
        }
    }

    public getAvatarModel():IModelData|null{
        return this.avatarModel;
    }

    public onDestroy() {
        this.gameWebsocket?.close();
    }

    public setphoenixRoot(phoenixRoot: PhoenixRoot) {
        this.phoenixRoot = phoenixRoot;
    }

    public initAccount(name: string, password: string) {
        this.account = new Account(name, password);
    }

    public isThirdPlatform(): boolean {
        return this.platform != PlatformDefine.PhoenixGame;
    }

    public setRequestTimeOut(timeOut: number) {
        this.platformHelp?.setRequestTimeOut(timeOut);
    }

    public checkLoginHasAvatar(): boolean {
        if (this.account == null) {
            return false;
        }
        if (this.account.getAvatarId() == 0) {
            return false;
        }
        return true;
    }

    private initAvatar(avatarResponse: AvatarResponse) {
        this.avatar = new Avatar(avatarResponse.name);
        this.avatar.setAvatarDataModel(this.avatarModel!);
        this.avatar.DeserializationData(avatarResponse.data, avatarResponse.useServer == 1);
        this.avatar.setId(avatarResponse.id);
        this.avatar.setCreateTime(avatarResponse.createTime!);
        this.avatar.setCredential(avatarResponse.credential);
        this.avatar.setIv(avatarResponse.iv);
        this.account?.setAvatarId(avatarResponse.id);
    }

    public clear() {
        this.account = null;
        this.avatar = null;
    }

    public async thirdLogin(thirdCode: string = '', cb:any): Promise<number> {
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        let url = '/auth/platformLogin';
        let input = new LoginPlatformInput();
        input.thirdCode = thirdCode;
        input.thirdPlatformType = this.platform;
        await this.requestPost<any>(
            url,
            input,
            (re:any) => {
                const platformRes: PlatformResponse = re.data;
                this.account!.setAccountName(platformRes.thirdAccount);
                cb(0);
            },
            (e:any) => {
                cb(e.code);
            }
        );
        return 0;
    }

    public async login(thirdCode: string = ''): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        console.log('login thirdCode:', thirdCode);
        if (
            this.account == null ||
            this.account.getAccountName() == '' ||
            this.account.getAccountName() == null ||
            this.account.getAccountName() == undefined
        ) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        let url = '/auth/login';
        let input = new LoginAccountInput();
        input.accountName = this.account.getAccountName();
        input.password = this.account.getAccountPassword();
        input.thirdCode = thirdCode;
        input.thirdPlatformType = this.platform;
        if (this.platform == PlatformDefine.PhoenixGame) {
            if (input.accountName == '' || input.password == '') {
                return -1;
            }
        }
        if (input.password != '') {
            input.password = Utils.Md5Encode(input.password);
        }
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input)
            .then(async (re) => {
                if (re.code == 0) {
                    const reAccount: AccountResponse = re.data;
                    this.account!.setAccountName(reAccount.accountName);
                    this.account!.setId(reAccount.accountId);
                    this.account!.setToken(reAccount.accessToken);
                    this.account!.setAvatarId(reAccount.avatarId);
                    this.account!.setThirdAccount(reAccount.thirdAccount);
                    this.account!.setTokenExpireTime(reAccount.tokenExpireTime);
                }
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async createAvatar(avatarData: any, name: string = ''): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        let url = '/avatar/create';
        let input = new CreateAvatarInput();
        input.account_id = this.account.getId();
        input.name = name;
        input.data = typeof avatarData == 'string' ? avatarData : JSON.stringify(avatarData);
        input.data = UtilsString.zlibEncode(input.data);
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                if (re.code == 0) {
                    const reAvatar: AvatarResponse = re.data;
                    reAvatar.data = UtilsString.zlibDecode(reAvatar.data);
                    this.initAvatar(reAvatar);
                }
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async getAvatar(): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        let url = '/avatar/query';
        let input = new GetAvatarInput();
        input.account_id = this.account.getId();
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                if (re.code == 0) {
                    const reAvatar: AvatarResponse = re.data;
                    reAvatar.data = UtilsString.zlibDecode(reAvatar.data);
                    this.initAvatar(reAvatar);
                }
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async getAvatarData(callBack:(data:any)=>{}): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        let url = '/avatar/query';
        let input = new GetAvatarInput();
        input.account_id = this.account.getId();
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                if (re.code == 0) {
                    const reAvatar: AvatarResponse = re.data;
                    reAvatar.data = UtilsString.zlibDecode(reAvatar.data);
                    callBack(reAvatar)
                }
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async updateAvtar(): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        if (this.avatar == null) {
            return ErrorLocalCode.AVATAR_NOT_CREATE;
        }
        let url = '/avatar/update';
        let input = new UpdateAvatarInput();
        input.account_id = this.account.getId();
        input.avatar_id = this.avatar.getId();
        input.data = UtilsString.zlibEncode(this.avatar.SerializeData());
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                if (re.code == 0) {
                    const reUpdate: AvatarUpdateResponse = re.data;
                    this.avatar!.setUpdateTime(reUpdate.updateTime);
                }
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async updateAvatarModuleToServer(moduleId:number): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        if (this.avatar == null) {
            return ErrorLocalCode.AVATAR_NOT_CREATE;
        }
        if (moduleId <= 0 || !this.avatar.checkModuelIsExist(moduleId)) {
            return ErrorLocalCode.MOUDLE_NOT_EXSIT;
        }
        let url = '/avatar/module/update';
        let input = new UpdateAvatarModuleInput();
        input.account_id = this.account.getId();
        input.avatar_id = this.avatar.getId();
        input.module_id = moduleId;
        input.data = this.avatar.serializeModuleData(moduleId);
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async getAvatarModuleFromServer(moduleId:number): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        if (this.avatar == null) {
            return ErrorLocalCode.AVATAR_NOT_CREATE;
        }
        let input = new GetAvatarModuleInput();
        let url = '/avatar/module/query';
        input.account_id = this.account.getId();
        input.avatar_id = this.avatar.getId();
        input.module_id = moduleId;
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                if (re.code == 0) {
                    const reData: AvatarModuleResponse = re.data;
                    this.avatar?.setModuleDataFromServer(reData.moduleId!, reData.data);
                }
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }


    public async getThirdAvatarModuleFromServer(moduleId:number, avatarId:number, callBack:(data:AvatarModuleResponse)=>void): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        if (this.avatar == null) {
            return ErrorLocalCode.AVATAR_NOT_CREATE;
        }
        let input = new GetAvatarModuleInput();
        let url = '/avatar/module/query';
        input.account_id = this.account.getId();
        input.avatar_id = avatarId;
        input.module_id = moduleId;
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                if (re.code == 0) {
                    const reData: AvatarModuleResponse = re.data;
                    callBack(reData);
                }
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async avatarSoreSet(storeKey:string, storeValue:string, storeLength:number, storeExpire:number = 48 * 3600): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        if (this.avatar == null) {
            return ErrorLocalCode.AVATAR_NOT_CREATE;
        }
        let input = new StoreSetInput();
        let url = '/avatar/store_set';
        input.account_id = this.account.getId();
        input.storeKey = storeKey;
        input.storeValue = storeValue;
        input.storeLength = storeLength;
        input.storeExpire = storeExpire;
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async avatarSoreGet(storeKey:string, callBack:(data:any)=>void): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        if (this.avatar == null) {
            return ErrorLocalCode.AVATAR_NOT_CREATE;
        }
        let input = new StoreGetInput();
        let url = '/avatar/store_get';
        input.account_id = this.account.getId();
        input.storeKey = storeKey;
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                if (re.code == 0) {
                    callBack(re.data);
                }
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async avatarSoreDel(storeKey:string, storeValue:string[]): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        if (this.avatar == null) {
            return ErrorLocalCode.AVATAR_NOT_CREATE;
        }
        let input = new StoreDelInput();
        let url = '/avatar/store_del';
        input.account_id = this.account.getId();
        input.storeKey = storeKey;
        input.storeValue = storeValue;
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async avatarWxQrcode(scene:string, version:string, width:number, callBack:(data:any)=>{}): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        if (this.avatar == null) {
            return ErrorLocalCode.AVATAR_NOT_CREATE;
        }
        let input = new WxQRCodeInput();
        let url = '/avatar/wx_qrcode';
        input.account_id = this.account.getId();
        input.scene = scene;
        input.env_version = version;
        input.width = width;
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
                if (re.code == 0) {
                    callBack(re.data);
                }
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async avatarShortLink(pageUrl:string, callBack:(data:any)=>{}): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        if (this.avatar == null) {
            return ErrorLocalCode.AVATAR_NOT_CREATE;
        }
        let input = new ShortLinkInput();
        let url = '/avatar/wx_short';
        input.account_id = this.account.getId();
        input.pageUrl = pageUrl;
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
                if (re.code == 0) {
                    callBack(re.data);
                }
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async updateAccountToken(): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        let url = '/auth/update/token';
        let input = new UpdateTokenInput();
        input.account_id = this.account.getId();
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                if (re.code == 0) {
                    const reUpdate: UpdateTokenResponse = re.data;
                    this.account!.setToken(reUpdate.accessToken);
                    this.account!.setTokenExpireTime(reUpdate.tokenExpireTime);
                }
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    /**
     * 更新订阅信息
     * @param subscribeType 订阅类型 number
     * @param sendTime  发送时间  string 格式 : yyyy-MM-dd HH:mm:ss
     * @returns 
     */
    public async updateSubscribe(subscribeType:number, sendTime:string): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        let url = '/subscribe/update';
        let input = new SubscribeInput();
        input.account_id = this.account.getId();
        input.avatar_id = this.avatar!.getId();
        input.subscribeType = subscribeType;
        input.sendTime = sendTime;
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }
    
    public async updateThirdAccountToken(): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        let url = '/account/update/third';
        let input = new UpdateAccountInput();
        input.account_id = this.account.getId();
        input.thirdToken = this.account.getThirdToken();
        input.thirdTokenExpireTime = this.account.getThirdTokenExpireTime();
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {})
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async updateServerTimer(): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        let url = '/time/now';
        let input = new UpdateServerTimeInput();
        let opCode = 0;
        await this.gameServerHttpClient
            .requestGet<any>(url, input)
            .then((re) => {
                this.serverTimer = re.data;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public queryServerInfo(callback: Function) {
        let url = '/server/query?ver=new';
        let input = new InputBase();
        let opCode = 0;
        this.requestGet<any>(
            url,
            input,
            (re:any) => {
                this.serverInfo = re.data;
                callback && callback(opCode);
            },
            (e:any) => {
                opCode = e.code;
                callback && callback(opCode);
            }
        );
    }

    public queryConfigs(callback: (code: number, data:any)=>void) {
        let url = '/game-config/configs?platform=' + this.platform!;
        let input = new InputBase();
        let opCode = 0;
        this.requestGet<any>(
            url,
            input,
            (re:any) => {
                callback && callback(opCode, re.data);
            },
            (e:any) => {
                opCode = e.code;
                callback && callback(opCode, null);
            }
        );
    }

    public async alipayReportAction(actionCode: string, actionFinishChannel: string): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        let url = '/alipay-report/report';
        let input = new AlipayReportInput();
        input.account_id = this.account.getId();
        input.actionCode = actionCode;
        input.actionFinishChannel = actionFinishChannel;
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                console.log('alipay report re:', re);
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    //#region 抖音相关

    public async bytejumpReportAction(actionCode: string, clickid: string) {
        if (this.gameServerHttpClient == null || this.platform != PlatformDefine.ByteJumpGame) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }

        let url = '/bytejump-report/report';
        let input = new BytejumpReportInput();
        input.account_id = this.account!.getId();
        input.actionCode = actionCode;
        input.actionFinishChannel = clickid;
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account!.getToken())
            .then(async (re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async bytejumpGetEcpm(cb: (data:any) => void) {
        if (this.gameServerHttpClient == null || this.platform != PlatformDefine.ByteJumpGame) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }

        let url = '/bytejump-report/ecpm';
        let input = new BytejumpGetEcpmInput();
        input.account_id = this.account!.getId();
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account!.getToken())
            .then(async (re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
                if (re.code == 0) {
                    cb && cb(re.data);
                }
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }
    
    public async kuaiShouReportAction(actionCode: string, clickid: string, eventProps: Map<string, number>) {
        if (this.gameServerHttpClient == null || this.platform != PlatformDefine.ByteJumpGame) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }

        let url = '/kuai-shou-report/report';
        let input = new KuaiShouReportInput();
        input.account_id = this.account!.getId();
        input.actionCode = actionCode;
        input.actionFinishChannel = clickid;
        input.eventProps = JSON.stringify(eventProps);
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account!.getToken())
            .then(async (re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public async serverCallThirdPlatform(thirdUrl: string, data: object): Promise<Number> {
        if (this.gameServerHttpClient == null) {
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        let url = '/account/call/third';
        let input = new CallThirdInput();
        input.account_id = this.account.getId();
        input.url = thirdUrl;
        input.data = JSON.stringify(data);
        let opCode = 0;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                this.thirdCallBackData = re.data;
                console.log('alipay report re:', re);
            })
            .catch((e) => {
                opCode = e.code;
            });
        return opCode;
    }

    public queryAccount(callback: Function) {
        if (this.account == null) {
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        let url = '/center/query';
        let input = new QueryAccountInput();
        input.accountName = this.account.getAccountName();
        let opCode = 0;
        this.requestPost<any>(
            url,
            input,
            (re:any) => {
                this.account!.setServers(re.data.servers);
                if (this.selectServerZone <= 0) {
                    let sid = this.account!.getDefauteServer();
                    if (sid > 0) {
                        opCode = this.selectServerBySid(sid);
                    } else {
                        opCode = this.randomSelectServer();
                    }
                }
                callback && callback(opCode);
            },
            (e:any) => {
                opCode = e.code;
                callback && callback(opCode);
            }
        );
    }

    public updateCenter(callback: Function) {
        if (this.account == null) {
            callback && callback(ErrorLocalCode.ACCOUNT_NOT_CREATE);
            return ErrorLocalCode.ACCOUNT_NOT_CREATE;
        }
        if (this.selectServerZone <= 0) {
            callback && callback(ErrorLocalCode.SERVER_NOT_SELECT);
            return ErrorLocalCode.SERVER_NOT_SELECT;
        }
        let url = '/center/update';
        let input = new CenterUpdateInput();
        input.accountName = this.account.getAccountName();
        input.sid = this.selectServerZone;
        // 这里是处理第三方平台,在此时还没有获取到账户,后续登录成功后会再次上传
        if (input.accountName == '') {
            return 0;
        }
        let opCode = 0;
        this.requestPost<any>(
            url,
            input,
            (re:any) => {
                callback && callback(opCode);
            },
            (e:any) => {
                opCode = e.code;
                callback && callback(opCode);
            }
        );
    }

    public async useCDKey(code:string): Promise<{code:number, extra:string}> {
        if (this.gameServerHttpClient == null) {
            return {code: ErrorLocalCode.SERVER_NOT_SELECT, extra: ""};
        }
        if (this.account == null) {
            return {code: ErrorLocalCode.ACCOUNT_NOT_CREATE, extra: ""};
        }
        if (this.avatar == null) {
            return {code: ErrorLocalCode.AVATAR_NOT_CREATE, extra: ""};
        }
        let url = '/cdkey/use';
        let input = new UseCdkeyInput();
        input.account_id = this.account.getId();
        input.avatar_id = this.avatar.getId();
        input.code = code;
        let opCode = 0;
        let extra = "";
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
                if (re.code == ErrorLocalCode.SUCCESS) {
                    extra = re.data;
                }
            })
            .catch((e) => {
                opCode = e.message.code;
            });
        return {code: opCode, extra: extra};
    }


    public async orderCreate(input:OrderCreateInput): Promise<{code:number, data:any}> {
        if (this.gameServerHttpClient == null) {
            return {code: ErrorLocalCode.SERVER_NOT_SELECT, data: null};
        }
        if (this.account == null) {
            return {code: ErrorLocalCode.ACCOUNT_NOT_CREATE, data: null};
        }
        if (this.avatar == null) {
            return {code: ErrorLocalCode.AVATAR_NOT_CREATE, data: null};
        }
        let url = '/pay/create';
        input.account_id = this.account.getId();
        let opCode = 0;
        let extra = null;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
                if (re.code == ErrorLocalCode.SUCCESS) {
                    extra = re.data;
                }
            })
            .catch((e) => {
                opCode = e.message.code;
            });
        return {code: opCode, data: extra};
    }

    public async orderQuery(input:OrderQueryInput): Promise<{code:number, data:any}> {
        if (this.gameServerHttpClient == null) {
            return {code: ErrorLocalCode.SERVER_NOT_SELECT, data: null};
        }
        if (this.account == null) {
            return {code: ErrorLocalCode.ACCOUNT_NOT_CREATE, data: null};
        }
        if (this.avatar == null) {
            return {code: ErrorLocalCode.AVATAR_NOT_CREATE, data: null};
        }
        let url = '/pay/query';
        input.account_id = this.account.getId();
        let opCode = 0;
        let extra = null;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
                if (re.code == ErrorLocalCode.SUCCESS) {
                    extra = re.data;
                }
            })
            .catch((e) => {
                opCode = e.message.code;
            });
        return {code: opCode, data: extra};
    }

    public async orderPayed(input:OrderPayedInput): Promise<{code:number, data:any}> {
        if (this.gameServerHttpClient == null) {
            return {code: ErrorLocalCode.SERVER_NOT_SELECT, data: null};
        }
        if (this.account == null) {
            return {code: ErrorLocalCode.ACCOUNT_NOT_CREATE, data: null};
        }
        if (this.avatar == null) {
            return {code: ErrorLocalCode.AVATAR_NOT_CREATE, data: null};
        }
        let url = '/pay/payed';
        input.account_id = this.account.getId();
        let opCode = 0;
        let extra = null;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
                if (re.code == ErrorLocalCode.SUCCESS) {
                    extra = re.data;
                }
            })
            .catch((e) => {
                opCode = e.message.code;
            });
        return {code: opCode, data: extra};
    }

    public async orderSend(input:OrderSendInput): Promise<{code:number, data:any}> {
        if (this.gameServerHttpClient == null) {
            return {code: ErrorLocalCode.SERVER_NOT_SELECT, data: null};
        }
        if (this.account == null) {
            return {code: ErrorLocalCode.ACCOUNT_NOT_CREATE, data: null};
        }
        if (this.avatar == null) {
            return {code: ErrorLocalCode.AVATAR_NOT_CREATE, data: null};
        }
        let url = '/pay/send';
        input.account_id = this.account.getId();
        let opCode = 0;
        let extra = null;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
                if (re.code == ErrorLocalCode.SUCCESS) {
                    extra = re.data;
                }
            })
            .catch((e) => {
                opCode = e.message.code;
            });
        return {code: opCode, data: extra};
    }

    public async cardChoose(input:CardChooseInput): Promise<{code:number, data:any}> {
        if (this.gameServerHttpClient == null) {
            return {code: ErrorLocalCode.SERVER_NOT_SELECT, data: null};
        }
        if (this.account == null) {
            return {code: ErrorLocalCode.ACCOUNT_NOT_CREATE, data: null};
        }
        if (this.avatar == null) {
            return {code: ErrorLocalCode.AVATAR_NOT_CREATE, data: null};
        }
        let url = '/game-logic/card/choose';
        input.account_id = this.account.getId();
        let opCode = 0;
        let extra = null;
        await this.gameServerHttpClient
            .requestPost<any>(url, input, this.account.getToken())
            .then((re) => {
                opCode = re.code ?? ErrorLocalCode.UNKNOWN_ERROR;
                if (re.code == ErrorLocalCode.SUCCESS) {
                    extra = re.data;
                }
            })
            .catch((e) => {
                opCode = e.message.code;
            });
        return {code: opCode, data: extra};
    }

    public selectServerBySid(sid: number): number {
        for (let i = 0; i < this.serverInfo!.servers!.length; i++) {
            // 判断sid是否等于服务器ID
            if (this.serverInfo!.servers![i].zone == sid) {
                this.selectServer(i);
                return ErrorLocalCode.SUCCESS;
            }
        }
        return ErrorLocalCode.SERVER_NOT_FOUNT;
    }

    public randomSelectServer(): number {
        if (this.serverInfo == null) {
            return ErrorLocalCode.SERVER_IS_NULL;
        }
        let index = -1;
        if(this.platform != PlatformDefine.PhoenixGame){  // 如果是平台,那只能使用https
            let canUse = [];
            for(let i = 0; i < this.serverInfo.servers!.length; i++){
                if(this.serverInfo.servers![i].web_ssl == 1){
                    canUse.push(i);
                }
            }
            if(canUse.length > 0){
                if(canUse.length == 1){
                    index = canUse[0];
                }else{
                    index = canUse[Math.floor(Math.random() * canUse.length)];
                }
            }
        }
        if(index == -1){
            index = Math.floor(Math.random() * this.serverInfo.servers!.length);
        }
        this.selectServer(index);
        return ErrorLocalCode.SUCCESS;
    }

    public selectServer(index?: number): number {
        if (this.serverInfo == null) {
            return ErrorLocalCode.SERVER_IS_NULL;
        }
        if (index == null || index == undefined) {
            this.gameServerHttpClient = new PhoenixHttpClient(
                this.platformHelp!,
                this.serverInfo.default!.web_address,
                this.serverInfo.default!.web_port + '',
                this.serverInfo.default!.web_ssl == 1,
                this.serverInfo.default!.web_secret
            );
            if(this.serverInfo.default!.address != '' && this.serverInfo.default!.port > 0){
                this.gameWebsocket = new WebSocketClient(this.serverInfo.default!.address, this.serverInfo.default!.port);
            }
            
            this.selectServerZone = this.serverInfo.default!.zone;
        } else {
            if (index > this.serverInfo.servers!.length - 1) {
                return ErrorLocalCode.SERVER_INDEX_OUT_OF_RANGE;
            }
            this.gameServerHttpClient = new PhoenixHttpClient(
                this.platformHelp!,
                this.serverInfo.servers![index].web_address,
                this.serverInfo.servers![index].web_port + '',
                this.serverInfo.servers![index].web_ssl == 1,
                this.serverInfo.servers![index].web_secret
            );
            if(this.serverInfo.servers![index].address != '' && this.serverInfo.servers![index].port > 0){
                this.gameWebsocket = new WebSocketClient(this.serverInfo.servers![index].address, this.serverInfo.servers![index].port);
            }
            this.selectServerZone = this.serverInfo.servers![index].zone;
        }
        this.updateServerTimer();
        return 0;
    }

    public getSelectServerZone(): number {
        return this.selectServerZone;
    }

    public getAccountIns(): Account | null {
        return this.account;
    }

    public getAvatarIns(): Avatar | null {
        return this.avatar;
    }

    public getServerTimer(): number {
        return this.serverTimer;
    }

    public setServerTimer(serverTimer: number): void {
        this.serverTimer = serverTimer;
    }

    public thirdPlatformLogin(cb:any) {
        this.platformHelp!.login(async (re:any) => {
            if (re == '') {
                cb(ErrorLocalCode.ACCOUNT_NOT_CREATE);
            } else {
                if (this.platformHelp!.needThirdPlatformLogin()){   // 需要服务器去获取平台账号信息
                    this.thirdLogin(re, cb);
                }else { // 平台登录直接返回了账号信息
                    this.account!.setAccountName(re);
                    cb(0);
                }
            }
        });
    }

    public gameLogin() {
        if (this.selectServerZone <= 0) {
            this.phoenixRoot!.loginCallBack(false, ErrorLocalCode.SERVER_NOT_SELECT);
        }
        this.login().then((re) => {
            this.phoenixRoot!.loginCallBack(re == 0, re.valueOf());
        });
    }

    public getThirdCallBackData(): any {
        return this.thirdCallBackData;
    }

    public async requestPost<T>(url: string, input: InputBase, success: Function, fail: Function) {
        this.httpClient!
            .requestPost(url, input)
            .then((res) => {
                success(res);
            })
            .catch((err) => {
                if (err && err.code) {
                    if(this.switchCenterServer()){
                        this.requestPost(url, input, success, fail);
                    }else{
                        fail({ code: ErrorLocalCode.RETRY_SWITCH_DOMAIN_LIMIT, message: '域名切换已达上限' });
                    }
                }
            });
    }

    public async requestGet<T>(url: string, input: InputBase, success: Function, fail: Function) {
        this.httpClient!
            .requestGet(url, input)
            .then((res) => {
                success(res);
            })
            .catch((err) => {
                if (err && err.code) {
                    if(this.switchCenterServer()){
                        this.requestGet(url, input, success, fail);
                    }else{
                        fail({ code: ErrorLocalCode.RETRY_SWITCH_DOMAIN_LIMIT, message: '域名切换已达上限' });
                    }
                }
            });
    }

    public loginGameServer(){
        this.avatar?.SendLogin();
        this.sendBundle();
    }

    public sendGamePacket(packet: Packet, send:boolean = true){
        if(send){
            messageManager.pushPacket(packet!, this.gameWebsocket!);
        }else{
            messageManager.pushPacket(packet!, null);
        }
    }

    public sendBundle() {
        messageManager.sendBundle(this.gameWebsocket!);
    }

    public EmitEvent(e:string, ...args:any[]) {
        this.phoenixRoot!.node.emit(e, ...args);
    }

    public setAvatarModuleData(moduleId:number, data:any){
        this.avatar!.setModuleData(moduleId, data);
    }

    public getAvatarModuleData(moduleId:number):any{
        return this.avatar!.getModuleData(moduleId);
    }
}
const phoenixIns = new Phoenix();
export default phoenixIns;
